#include "Matrix.h"
#include "FVector.h"
#include "FMatrixUtil.h"
#include <iostream>
#include <iomanip>

using namespace std;

#define Matrix FMatrix

typedef yy::math::Matrix<4, 4, double> Matrix4d;
typedef yy::math::Matrix<3, 3, double> Matrix3d;
typedef yy::math::Matrix<2, 2, double> Matrix2d;

typedef yy::math::FVector<2, double> Vector2d;
typedef yy::math::FVector<3, double> Vector3d;
typedef yy::math::FVector<4, double> Vector4d;

template<class T>
void dump_matrix(T const& A)
{
	int m = A._m();
	int n = A._n();
	for (int i = 0; i < m; ++i)
	{
		for (int j = 0; j < n; ++j)
		{
			cout << setw(14) << fixed << A(i, j);
		}
		cout << endl;
	}
	cout << endl;
}

template<class T>
void dump_vector(T const& A)
{
	int n = A._n();
	for (int i = 0; i < n; ++i)
		cout << setw(14) << fixed << A[i];
	cout << endl;
}

void test1();
void test2();
void test3();
void test4();
void test5();
void test6();

int main()
{
	test4();
	test3();
	test2();
	test1();
	test5();
	test6();
	return 0;
}

void test6()
{
	std::vector<Vector2d> X;
	for (int i = 0; i < 5; ++i) {
		Vector2d x{ (double)i,(double)i * 2 };
		X.push_back(Vector2d((double)i, (double)i * 2));
	}
	Matrix2d A;
	A.makeIdentity();
	A(0, 1) = 1.0;
	auto Y = X * A;
	for (auto iter = Y.begin(); iter != Y.end(); ++iter)
		dump_vector(*iter);
	cout << endl;
	Y = A * X;
	for (auto iter = Y.begin(); iter != Y.end(); ++iter)
		dump_vector(*iter);
}

void test5()
{
	Vector2d x{ 1,2 };
	Matrix2d A;
	A.makeIdentity();
	auto y = x * A;
	dump_vector(y);
	y = A * x;
	dump_vector(y);
}

void test4()
{
	Vector2d a{ 1,2 };
	auto b = a;
	b.makeZero();
	b.makeIdentity(1);
	auto c = a - b;
	c = a + b;
	c = a * 1.0;
	c = 4.0 * a;
	dump_vector(a);
	dump_vector(c);
	c.x() = 100.0;
	c.y() = 3.0;
	cout << c.length() << " " << c.length2() << endl;
}

void test1()
{
	Matrix2d a = { 1, 1, 1,2 };
	auto c = yy::math::Inverse(a);

	//dump_matrix(c);
	auto d = c * a;
	//dump_matrix(d);
}

void test2()
{
	Matrix4d a = { 1, 1, -1, 4, 1, -1, 1, 2, 1, 5, 3, 16, 1, 2, -3, 5 };
	Matrix4d b = a;

	Matrix4d c = a - b;
	auto d = yy::math::Transpose(b);

	c = yy::math::Inverse(a);

	dump_matrix(c);
	d = c * a;
	dump_matrix(d);
}

void test3()
{
	Matrix4d a = { 3, 1, -1, 4, 1, -1, 1, 2, 1, 5, 3, 16, 1, 2, -3, 5 };
	Matrix4d b = a;

	Matrix4d c = a - b;
	c = a + b;
	c = a / 1.0;
	c = a * 1.0;
	auto d = yy::math::Transpose(b);

	c = yy::math::Inverse(a);
	dump_matrix(c);
	d = c * a;
	dump_matrix(d);
}